package org.fjsei.yewu.graphql.directive;

import graphql.schema.DataFetcher;
import graphql.schema.FieldCoordinates;
import graphql.schema.GraphQLFieldDefinition;
import graphql.schema.GraphQLFieldsContainer;
import graphql.schema.idl.SchemaDirectiveWiring;
import graphql.schema.idl.SchemaDirectiveWiringEnvironment;
import org.fjsei.yewu.graphql.InvalidException;
import org.fjsei.yewu.graphql.MyDataFetcherFactories;

import static java.lang.String.format;


/** 分页从数据库搜索，本来就要比反射Jpa更早一步。
    graphql-java-tools太主动太早获取Set<>数据。
 添加@Component @Service 支持注入Repository。 依旧会"this.approvalStmService" is null
 实际上配置文件java注册Directive "dbpage"时用了=new()本类的。
 特别注意 加入本类被加@Service注释,后果会是：没有"dbpage"注解的接口也会运行到这里.pageDataFetcher(field.getName(),originalFetcher, ((dataFetchingEnvironment, value) -> {
*/
@Deprecated(since="Spring for Graphql上了", forRemoval=true)
public class DbpageDirective implements SchemaDirectiveWiring {
    //试试直接静态装载类
    //@Autowired private ApprovalStmService approvalStmService;
    /*
    DataFetcherFactoryEnvironment仅仅包裹GraphQLFieldDefinition；
    GraphQLCodeRegistry实际提供DataFetcherFactory最后搭配DataFetcherFactoryEnvironment才能生成DataFetcher
    */

    @Override
    public GraphQLFieldDefinition onField(SchemaDirectiveWiringEnvironment<GraphQLFieldDefinition> env) {
        GraphQLFieldDefinition field = env.getElement();
        GraphQLFieldsContainer parentType = env.getFieldsContainer();
        // build a data fetcher that transforms the given value to uppercase
        DataFetcher originalFetcher = env.getCodeRegistry().getDataFetcher(parentType, field);

        DataFetcher dataFetcher = MyDataFetcherFactories
                .pageDataFetcher(field.getName(),originalFetcher, ((dataFetchingEnvironment, value) -> {
                    //这个嵌套函数块：实际就是注入逻辑部分，每次请求运行的部分；除此之外的那些代码仅仅在系统启动时运行到的。
                    //有可能多个模型的内省字段是同一个，而且允许单独非内省方式地调用接口，用函数名字作为关键字。value是graphQL-Query-函数名。
                    FieldCoordinates fieldCoordinates= FieldCoordinates.coordinates("Query",(String) value);
                    DataFetcher agentDataFetcher=env.getCodeRegistry().getDataFetcher(fieldCoordinates, (GraphQLFieldDefinition)env.getElement());
                    //直接舍弃掉原本设计好的DataFetcher(),改成执行"Query : 同名字的接口"代理函数。
                    Object valueRet=null;
                    try {
                        valueRet= agentDataFetcher.get(dataFetchingEnvironment);
                    } catch (Exception e) {
                        throw new InvalidException(format("agentDataFetcher fail: '%s'; %s", value, e.getMessage()), e);
                    }
                    //返回值才关键，替换本来应该让旧的DataFetcher读取给出的数据。
                    return valueRet;
                    //这个嵌套函数块 End;
                }));

        // now change the field definition to use the new uppercase data fetcher
        //实际上等于也修改了DataFetcher一次了。
        env.getCodeRegistry().dataFetcher(parentType, field, dataFetcher);
        return field;
    }

}

